#pragma once

#include "defines.h"
#include "platform/vk/vk_device_context.h"
#include "platform/vk/vk_swapchain.h"
#include "platform/vk/vk_graphics_pipeline.h"
#include "platform/vk/vk_texture.h"
#include "platform/vk/vk_texture_sampler.h"
#include "platform/vk/vk_uniform_buffer.h"

#include "scene/mesh.h"


namespace vkrender
{
    class MeshRenderer
    {
        struct MVPUBO
        {
            glm::mat4 model;
            glm::mat4 view;
            glm::mat4 proj;
        } ubo;

    public:
        std::shared_ptr<VulkanDeviceContext> context;
        std::shared_ptr<VulkanGraphicsPipeline> graphicsPipeline;

        VulkanSwapChain* swapchain;
        VkPipelineLayout pipelineLayout;

        VkDescriptorPool descriptorPool;
        VkDescriptorSetLayout descriptorSetLayout;

        std::vector<VkDescriptorSet> descriptorSets;
        // std::vector<VkCommandBuffer> commandBuffers;
        std::vector<VulkanUniformBuffer> uniformBuffers;

        std::shared_ptr<VulkanTexture> texture;
        std::shared_ptr<VulkanTextureSampler> sampler;


    public:
        MeshRenderer(
            const std::shared_ptr<VulkanDeviceContext>& context,
            const std::shared_ptr<VulkanSwapChain>& swapchain
        );
        ~MeshRenderer();

        void bind(uint32_t imageIndex, VkCommandBuffer cmd, const glm::mat4& proj, const glm::mat4& view);
        void draw(uint32_t imageIndex, VkCommandBuffer cmd, const std::shared_ptr<VulkanModel>& mesh, const glm::mat4& model_matrix);
        // VkCommandBuffer endDraw(uint32_t imageIndex);

        void adjustForSwapchain(const std::shared_ptr<VulkanSwapChain>& swapchain);
    private:
        void createDescriptorPool();
        void createDescriptorSetLayout();
        void createPipelineLayout();
        void createPipeline();
        void createDescriptorSets();
        void createUniformBuffers();

        void updateDescriptorSets();
        void updateUniformBuffer(uint32_t imageIndex);
        // void createCommandBuffers();
        // void freeCommandBuffers();
    };
}
